<?php

/**
 * @desc Exclude magic_quotes_gpc influence. Implemented on the application level
 * as PHP can be started in CGI mode. 
 *
 */
if (get_magic_quotes_gpc()) {
    array_apply_recursive($_GET, 'stripslashes');
    array_apply_recursive($_POST, 'stripslashes');
    array_apply_recursive($_COOKIE, 'stripslashes');
    array_apply_recursive($_REQUEST, 'stripslashes');
}

/**
 * @desc Application request in HTTP mode. 
 *
 */
class Kernel_Request_Http extends Kernel_Request_Abstract 
{

    /**
     * @desc Array containing url sections.
     *
     * @var array
     */
    private $_uri = array();

    /**
     * ID value set in form "/foo/bar/baz/id.html". 
     *
     * @var integer
     */
    private $_id;
    
    /**
    * @desc ID extension
    * 
    * @param string
    */
    private $_ext; 
    
    /**
    * @desc Application language
    * 
    * @param string
    */
    private $_lang; 

    public function __construct() 
    {
        // define resource path exclude subdir in which site is located.
        if (!preg_match('/(.*?)(([a-z0-9]+)\.([a-z0-9]*))?$/', $this->_getRequestUri(), $matches)) {
            // in principle it's impossible
            trigger_error('Unable to parse URI', E_USER_ERROR);
            return;
        }
        
        $uri = trim($matches[0], '/');
        $this->_uri = strlen($uri) > 0 ? explode('/', $uri) : array();
        $this->_id = isset($matches[3]) ? $matches[3] : null;
        $this->_ext = isset($matches[3]) ? (string)strtolower($matches[4]) : null; 
        
        // consider that first uri param is language in miltulanguage application
        if ($this->isMultilang()) {
            $this->_lang = array_shift($this->_uri);
        }
    }
    
    /**
     * Return ID value.
     *
     * @return  integer
     */
    public function id() 
    {
        return $this->_id;
    }
    
    /**
     * Return extension.
     *
     * @return  string
     */
    public function ext() 
    {
        return $this->_ext;
    }
    
    /**
     * Return language.
     *
     * @return  string
     */
    public function lang() 
    {
        return $this->_lang;
    }

    /**
     * @desc Return whether current resource is requested by POST method. 
     *
     * @return  boolean
     */
    public function isPost() 
    {
        return 'POST' == $_SERVER['REQUEST_METHOD'];
    }

    /**
     * @desc Return GET param value. 
     *
     * @param   string  $param
     * @param   mixed   $default
     * @return  mixed
     */
    public function get($param, $default = null) 
    {
        return $this->hasGet($param, true) ? $_GET[$param] : $default;
    }

    /**
     * @desc Return POST param value. 
     *
     * @param   string  $param
     * @param   mixed   $default
     * @return  mixed
     */
    public function post($param, $default = null) 
    {
        return $this->hasPost($param, true) ? $_POST[$param] : $default;
    }

    /**
     * @desc Return whether specified param is set. 
     *
     * @param   string  $param
     * @param   boolean $empty
     * @return  boolean
     */
    public function has($param, $empty = false) 
    {
        trigger_error(__METHOD__ . ' is not implemented');
    }

    /**
     * @desc Return whether specified GET param is set. 
     *
     * @param   string  $param
     * @param   boolean $empty
     * @return  boolean
     */
    public function hasGet($param, $empty = false) 
    {
        return $empty ? isset($_GET[$param]) : !empty($_GET[$param]);
    }

    /**
     * @desc Return whether specified POST param is set. 
     *
     * @param   string  $param
     * @param   boolean $empty
     * @return  boolean
     */
    public function hasPost($param, $empty = false) 
    {
        return $empty ? isset($_POST[$param]) : !empty($_POST[$param]);
    }

    /**
     * @desc Return COOKIE param. 
     *
     * @param   string  $param
     * @param   mixed   $default
     * @return  mixed
     */
    public function cookie($param, $default = null) 
    {
        return isset($_COOKIE[$param]) ? $_COOKIE[$param] : $default;
    }

    /**
     * @desc Get uri section value by index otherwise return whole array. 
     *
     * @param   integer $index
     * @param   mixed   $default
     * @return  mixed
     */
    public function uri($index = null, $default = null) 
    {
        return !is_null($index)
            ? isset($this->_uri[$index])
                ? $this->_uri[$index]
                : $default
            : $this->_uri;
    }

    /**
     * @desc Return whether current resource is requested via secure protocol. 
     *
     * @return  boolean
     */
    public function secure() 
    {
        return isset($_SERVER['HTTPS']) && 'on' == $_SERVER['HTTPS'];
    }

    /**
     * @desc Return whole url for the current resource. 
     *
     * @return  string
     */
    public function url($secure = null) 
    {
        return ((null === $secure ? $this->secure() : $secure) ? 'https' : 'http')
            . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
    }

    /**
     * @desc Return query string in the unmodified state. 
     *
     * @return  string
     */
    public function query($delimiter = false) 
    {
        $query = $_SERVER['QUERY_STRING'];
        return $delimiter
            ? strlen($query) > 0 ? '?' . $query : ''
            : $query;
    }

    /**
     * @desc Return value similar to $_SERVER['REQUEST_URI'] but relatively to 
     * the site root. 
     *
     * @return  string
     */
    public function requestUri() 
    {
        return substr($_SERVER['REQUEST_URI'], strlen(dirname($_SERVER['SCRIPT_NAME'])));
    }
    
    /**
    * Return HTTP_RERFERER value or false on failure.
    * 
    * @return string
    */
    public function referer() 
    {
        return isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : false;
    }

    /**
     * @desc Return whether form was submitted by the specified button name. 
     *
     * @param   string  $name
     * @return  mixed
     */
    public function submitted($name) 
    {
        if (1 == func_num_args() && !is_array($name)) {
            return $this->_submitted($name);
        }
        foreach (array_values_recursive(func_get_args()) as $name) {
            if ($this->_submitted($name)) {
                return $name;
            }
        }
        return false;
    }

    /**
     * @desc Return whether form was submitted by the specified button name.
     *
     * @param   string  $name
     * @return  boolean
     */
    private function _submitted($name) 
    {
        $data = $this->isPost() ? $_POST : $_GET;
        return isset($data[$name]) || isset($data[$name . '.x']) || isset($data[$name . '_x']);
    }

    /**
     * @desc Return current resource address relatively to the site root. 
     * Consider that redirection is always goes to the /index.php
     *
     * @return  string
     */
    private function _getRequestUri() 
    {
        return substr(@$_SERVER['REDIRECT_URL'], strlen(dirname($_SERVER['SCRIPT_NAME'])));
    }
    
}
